home *** CD-ROM | disk | FTP | other *** search
-
- /* Copyright (C) 1988, 1989 Herve' Touati, Aquarius Project, UC Berkeley */
-
- /* Copyright Herve' Touati, Aquarius Project, UC Berkeley */
-
- #include <stream.h>
- #include "hash_table.h"
-
- static unsigned simple_hash(int i) {return (unsigned) i;}
- static unsigned simple_equal(int i, int j) {return (i == j);}
-
- void HashTable::allocate()
- {
- char* malloc(int);
- int object_size = sizeof(HashTableEntry*) + sizeof(HashTableEntry);
- alloc_area = malloc(size * object_size);
- if (alloc_area == 0) {
- cerr << "Can't allocate this hash table\n";
- exit(1);
- }
- table = (HashTableEntry**) alloc_area;
- next_entry = (HashTableEntry*) (table + size);
- next_entry0 = next_entry + size;
- clear();
- }
-
- void HashTable::reenter_old_data(int old_size, HashTableEntry** old_table)
- {
- register HashTableEntry** c;
- for (int i = 0; i < old_size; i++) {
- c = &old_table[i];
- while (*c != 0) {
- bind((*c)->key, (*c)->value);
- c = &((*c)->next);
- }
- }
- }
-
- void HashTable::rehash()
- {
- void free(char*);
- char* old_alloc_area = alloc_area;
- HashTableEntry** old_table = table;
- int old_size = size;
- size <<= 1;
- allocate();
- reenter_old_data(old_size, old_table);
- free(old_alloc_area);
- }
-
- HashTable::HashTable(int SIZE)
- {
- size = SIZE;
- allocate();
- }
-
- HashTableEntry** HashTable::get_cell(int n)
- {
- HashTableEntry** c = &table[(unsigned) n % size];
- while (*c != 0 && (*c)->key != n)
- c = &((*c)->next);
- return c;
- }
-
- void HashTable::bind(int n1, int n2)
- {
- HashTableEntry** c = get_cell(n1);
- if (*c == 0) {
- if ((*c = new_cell()) == 0) {
- rehash();
- bind(n1, n2);
- return;
- }
- (*c)->next = 0;
- (*c)->key = n1;
- }
- (*c)->value = n2;
- }
-
- int HashTable::get(int n)
- {
- HashTableEntry** c = get_cell(n);
- if (*c == 0) {
- status = HASH_MISS;
- return 0;
- } else {
- status = HASH_HIT;
- return (*c)->value;
- }
- }
-
- void HashTable::clear()
- {
- register HashTableEntry** c = table;
- register HashTableEntry** c0 = table + size;
- for (; c < c0; c++)
- *c = 0;
- next_entry = (HashTableEntry*) (table + size);
- }
-
- void HashTable::reset()
- {
- for (int i = 0; i < size; i++)
- if (table[i] != 0) {
- next_cell = &table[i];
- next_index = i;
- return;
- };
- next_cell = 0;
- next_index = size;
- }
-
- HashTableEntry* HashTable::next()
- {
- HashTableEntry* result;
- if (next_index == size)
- return 0;
- result = *next_cell;
- next_cell = &((*next_cell)->next);
- if (*next_cell != 0)
- return result;
- next_index++;
- for (int i = next_index; i < size; i++)
- if (table[i] != 0) {
- next_cell = &table[i];
- next_index = i;
- return result;
- };
- next_cell = 0;
- next_index = size;
- return result;
- }
-
- void HashTable::print()
- {
- reset();
- HashTableEntry* e;
- while (e = next())
- e->print();
- }
-
- #ifdef DEBUG_HASH_TABLE
-
- void out_of_store()
- {
- cerr << "operator new failed: out of store\n";
- exit(1);
- }
- typedef void (*PF)();
-
- extern PF set_new_handler(PF);
-
- main() {
- int i1, i2;
- HashTable T;
- set_new_handler(&out_of_store);
- cout << "Try out hash tables \n";
- for (;;) {
- cin >> i1 >> i2;
- if (cin.rdstate() != _good)
- break;
- T.bind(i1, i2);
- cin >> i1;
- cout << T.get(i1) << "\n";
- }
- T.print();
- cout << "clear\n";
- T.clear();
- T.print();
- cout << "add one\n";
- T.bind(12,23);
- T.print();
- }
- #endif
-